import { keywordCompare } from '@gnlab/utils'
import { App } from 'antd'
import { OrderedMap } from 'immutable'
import { useStreams } from '@/lib/utils'
import services from '@/services'
import { type GroupContact } from '@/services/contact-types'
import { getGroups } from '@/services/contact-types/groups/api'
import { type ContactInfo } from '../logics'

export function useChooseTags() {
  const [allTags] = useStreams(services.groups.tags)
  useEffect(() => void services.groups.loadTags(), [])

  const [tagIds, setTagIds] = useState<number[]>([])
  const cancelChooseTag = useCallback(
    (tagId: number) => setTagIds(tagIds => tagIds.filter(v => v !== tagId)),
    [],
  )

  const choosedTags = useMemo(
    () => allTags.filter(tag => tagIds.includes(tag.id)),
    [allTags, tagIds],
  )

  return { tagIds, setTagIds, cancelChooseTag, choosedTags }
}

export enum GroupType {
  群主 = '群主',
  外部群 = '外部群',
}

export function useGroups(
  wxids: string[],
  tagIds?: number[],
  types?: GroupType[],
  keyword: string = '',
) {
  const { message } = App.useApp()

  // 无论是否按标签筛选，都不能从 services.groups.list 里取，要调接口。
  // 因为选中的企微可能不是当前用户的，groups.list 里没有对应的群
  const [allGroups, setAllGroups] = useState<GroupContact[]>([])
  const allGroupsMap = useMemo(() => OrderedMap(allGroups.map(g => [g.id, g])), [allGroups])
  useEffect(() => {
    setAllGroups([])
    void getGroups(wxids, tagIds).then(res => {
      if (res.success) setAllGroups(res.data)
      else void message.error('加载群列表失败：' + res.error)
    })
  }, [message, wxids, tagIds])

  const filteredGroups = useMemo(() => {
    const filteredMap = new Map<string, GroupContact>() // conversationId => group
    for (const group of allGroups) {
      if ((types ?? []).includes(GroupType.群主) && !group.isOwner) continue
      if ((types ?? []).includes(GroupType.外部群) && !group.isExternal) continue
      if (keyword && !keywordCompare(keyword, group.name) && !keywordCompare(keyword, group.remark))
        continue
      // 若多个企微在同一个群里，只保留其中一个（优先保留是群主的那个），以避免重复发送
      if (filteredMap.has(group.conversationId) && !group.isOwner) continue
      filteredMap.set(group.conversationId, group)
    }
    return [...filteredMap.values()]
  }, [allGroups, types, keyword])

  return {
    allGroupsMap,
    allGroups,
    filteredGroups,
  }
}

// 全选 / 反选（在过滤了的群范围内）
export function useChooseAll(
  filteredGroups: GroupContact[],
  validChoosedMap: OrderedMap<string, ContactInfo>,
  setChoosed: (choosed: ContactInfo[]) => void,
) {
  const hasChoosed = useMemo(
    () => !!filteredGroups.find(group => validChoosedMap.has(group.id)),
    [filteredGroups, validChoosedMap],
  )
  const isChoosedAll = useMemo(
    () => filteredGroups.every(group => validChoosedMap.has(group.id)),
    [filteredGroups, validChoosedMap],
  )

  const chooseAll = useCallback(() => {
    let map = validChoosedMap
    for (const group of filteredGroups) map = map.set(group.id, group)
    setChoosed([...map.values()])
  }, [filteredGroups, validChoosedMap, setChoosed])

  const chooseReverse = useCallback(() => {
    let map = validChoosedMap
    for (const group of filteredGroups) {
      if (map.has(group.id)) map = map.delete(group.id)
      else map = map.set(group.id, group)
    }
    setChoosed([...map.values()])
  }, [filteredGroups, validChoosedMap, setChoosed])

  const clearChoose = useCallback(() => {
    let map = validChoosedMap
    for (const group of filteredGroups) map = map.delete(group.id)
    setChoosed([...map.values()])
  }, [filteredGroups, validChoosedMap, setChoosed])

  return {
    hasChoosed,
    isChoosedAll,
    chooseAll,
    chooseReverse,
    clearChoose,
  }
}
